/*
										Melonracer Redux by Stephen Swires & Gmod4Ever
	==================================================================================================================================================
	The MIT License
	Copyright (c) 2006 Stephen Swires & Gmod4Ever

	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
	Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
	WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
	OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
	OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
	==================================================================================================================================================
*/

// Shared shit
include("shared.lua")

// client-side scripts
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_init.lua" )

// Most of this file is Gmod4Ever's code, so credits go to him!
Melon_Model				 = 	"models/props_junk/watermelon01.mdl"
Forward_Thrust			 = 	170
Reverse_Thrust			 =	-40
MelonRacer				 = 	{}
MelonRacer.PlayerData	 = 	{}
MelonRacer.StatsData	 =	{}
MelonRacer.CheckPoints	 =	{}

// check point counter
CheckPointID			 =	0

// MACRO: For applying force to our melon
local function MelonForce( pl, force )

	local ent = MelonRacer.PlayerData[ pl:UniqueID() ].Melon // entity object
			
	// yep, we have a melon
	if MelonRacer.PlayerData[ pl:UniqueID() ].Melon == nil then return end
			
	// make sure we're valid, or we get a crash :downs:
	if ( ent:IsValid() ) then
				
		local ang = pl:GetAimVector( ) // apply the force to the direction we're looking at.
		local vel = force*ang // our new velocity.
					
		local phys = ent:GetPhysicsObject( ) // physics object
		phys:ApplyForceCenter(vel) // and apply
					
	end
			
end

function GM:Think()

	// get all the players on the server (every frame!)
	local all_players = player.GetAll()
	
	// now loop
	for k, v in pairs(all_players) do
			
		if v:KeyDown(IN_FORWARD) then // we're holding down w
			MelonForce( v, Forward_Thrust )
		elseif v:KeyDown(IN_BACK) then // reverse!!
			MelonForce( v, Reverse_Thrust )
		end	
		
	end
	
end


function GM:Initialize() // we don't need to set the tables up here in a game mode
	Msg( "[Melonracer] Gamemode started...\n")
	
	// initializing some vars
	MelonRacer.StatsData.BestTime		=	0
	MelonRacer.StatsData.BestTimeString	=	"0:00.00"
	MelonRacer.StatsData.BestSetter		=	"None"
	
	MelonRacer.StatsData.FirstPlace		=	0
	MelonRacer.StatsData.SecondPlace	=	0
	MelonRacer.StatsData.ThirdPlace		=	0
	
	// get the checkpoints list
	local CheckPoints = ents.FindByClass("func_checkpoint")
	
	// add the checkpoints into the "database"
	for k, v in pairs( CheckPoints ) do
		MelonRacer.CheckPoints[ v:GetNetworkedInt( "checkpoint" ) ] = v
	end
	
end

function GM:PlayerDisconnected( pl ) // disconnect, we need to get rid of the melon they left behind
	if( MelonRacer.PlayerData[ pl:UniqueID() ].Melon != nil ) then
		
		// do our breaking shit.
		local ent = MelonRacer.PlayerData[ pl:UniqueID() ].Melon // entity object
		
		if( ent:IsValid() ) then
			ent:Fire( "break", "0", "0" ) // break it!
		end
		
	end
end

function GM:PlayerInitialSpawn( pl )

	local UID = pl:UniqueID() // unique  id for the table
	MelonRacer.PlayerData[UID] = {} // empty it first, just in case we have data from another user.
	
	// initialize some data
	MelonRacer.PlayerData[UID].Melon		= 	nil // they have no melon...yet!
	MelonRacer.PlayerData[UID].CheckPoint	=	0
	MelonRacer.PlayerData[UID].Laps			=	0
	MelonRacer.PlayerData[UID].LapTime		=	0
	MelonRacer.PlayerData[UID].LapStart		=	0
	MelonRacer.PlayerData[UID].LapBest		=	0
	MelonRacer.PlayerData[UID].FinishedRace	=	false
	
	pl:PrintMessage( HUD_PRINTTALK, "[Melonracer] Welcome to Melonracer. Please drive your melon carefullly. Press F1 for help." )
	
end


function GiveMeMyMelon( pl )
	
	local UID 	=	 pl:UniqueID() // get our unique id
	local ent 	=	 ents.Create("prop_physics") // create the entity which will be our melon
	local pos 	=	 pl:GetPos() // and get our position
	
	ent:SetModel( Melon_Model ) // give the ent a model, the melon that is
	ent:SetPos(pos) // set it to our position, which will be where the info_player_* are
	
	// spawn and activate it
	ent:Spawn()
	ent:Activate()
	
	// this is what the old version did, it made us spectate the entity, and this is what the new one does.
	pl:Spectate(4)
	pl:SpectateEntity(ent)
	
	// technically, there shouldn't be any weapons, but get them stripped just in case.
	pl:StripWeapons()
	
	// occupy our player data table with the entity stuff.
	MelonRacer.PlayerData[UID].Melon = ent
	
	// network the melon entity, for like getting the velocity and shit.
	pl:SetNetworkedEntity( "Melon", MelonRacer.PlayerData[UID].Melon )

end

function GM:PlayerSpawn( pl )
	timer.Simple( 0.1, GiveMeMyMelon, pl )
	MelonRacer.PlayerData[ pl:UniqueID() ].LapStart = CurTime()
end

function GM:PropBreak( pl, ent )

	// remember, pl won't be the object of the actual player because technically the server is controlling the melon! 
	// get all the players on the server
	local AllPlayers = player.GetAll()

	// loop through them all.
	for k, v in pairs(AllPlayers) do
		
		// the unique id of the player, which is used in the player data table.
		local UID = v:UniqueID()
		
		if (MelonRacer.PlayerData[UID].Melon == ent) then
			v:KillSilent() // kill us :/
		end
		
	end
	
end

// this finds the owner of melon
function GM:WhoTheFucksMelon( entity )
	for k, v in pairs( MelonRacer.PlayerData ) do
		
		local UID = v
		local Melon = MelonRacer.PlayerData[UID].Melon
		
		if( entity:EntIndex() == Melon:EntIndex() ) then
			return UID
		end
		
	end
	
	return 0
end

// triggered when a player's melon goes through a checkpoint
function GM:DoCheckpoint( pl, ent )

	local LastCheckPoint = MelonRacer.PlayerData[ pl:UniqueID() ].CheckPoint
	local ThisCheckPoint = ent:GetNetworkedInt( "checkpoint" )
	
	if( (LastCheckPoint == table.Count( MelonRacer.CheckPoints ) && ThisCheckPoint == 1) || LastCheckPoint == 0 ) then
		Msg( "Lap " )
		
		if(LastCheckPoint == 0) then
			Msg( "- Start of race\n" )
		else
			Msg("Complete\n")
			
			local ThisLap = CurTime() - MelonRacer.PlayerData[ pl:UniqueID() ].LapStart // our lap time in seconds.
			MelonRacer.PlayerData[ pl:UniqueID() ].LapTime = ThisLap
			MelonRacer.PlayerData[ pl:UniqueID() ].LapStart = CurTime() // this should be last here
		
			local HUDLap = RecipientFilter()
			HUDLap:AddPlayer( pl )
		
			umsg.Start( "hud_lap", HUDLap )
				umsg.Float( ThisLap )
			umsg.End()
		end
		
	elseif( ThisCheckPoint == LastCheckPoint+1 ) then
		Msg( "Checkpoint\n" )
	elseif( ThisCheckPoint == LastCheckPoint ) then
		Msg( "Backwards\n" )
	else
		Msg( "Still Going Backwards!\n" )
	end
	
end
